/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package idp.dashboard;

import idp.communication.MessageController;
import idp.communication.MessageListener;
import idp.utils.DateFormatter;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.sql.Time;
import java.util.Calendar;
import java.util.Stack;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.print.attribute.standard.DateTimeAtCompleted;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;

/**
 * 
 * @author admin
 */
public class MainPanel extends JPanel implements MessageListener
{
	private BufferedImage imgIncline, imgGlass, imgCompass, imgCompassNeedle, imgCompassBoat,
			imgSensor, imgBackground, imgNeedle, imgDigitalBackground, imgToerentalBackground,
			imgDigitalGlass, imgSwitchOn, imgSwitchOff, imgSwitchWarning, imgLabelGrootZeil,
			imgLabelFok, imgLabelHandmatig, imgLabelMotor, imgLabelRfids, imgLabelVerbinding, imgLabelAccu, imgLabelToerental, imgLabelRoerstand;

	private double angIncline = 0, angCompass = 0, angWind = 0, angGrootzeil = 0, angFok = 0, angToeren = 0, angRoer;

	private int _windCount, _fzeilCount, _gzeilCount, _hellingCount,
			_richtingCount, _toerenCount;

	private float _windValue, _fzeilValue, _gzeilValue, _hellingValue,
			_richtingValue, _toerenValue, _accuValue;
	
	private String _time = "";
	
	private Vector<String> _rfidValues = new Vector<String>();
	
	private JList listRfid = new JList(_rfidValues);

	private boolean _manualMode;

	private boolean _motorMode;

	private boolean _isConnected;

	private boolean _accuWarning;
	
	/**
	 * Constructor
	 */
	public MainPanel()
	{
		MessageController.addListener(this);
		
		imgIncline = loadImage("lib/img/sensor_0_back.png");
		imgCompass = loadImage("lib/img/sensor_1_back.png");
		imgCompassNeedle = loadImage("lib/img/sensor_1_needle.png");
		imgCompassBoat = loadImage("lib/img/sensor_1_boat.png");
		imgSensor = loadImage("lib/img/sensor_2_back.png");
		imgGlass = loadImage("lib/img/sensor_glass.png");
		imgNeedle = loadImage("lib/img/sensor_2_needle.png");
		imgBackground = loadImage("lib/img/background.jpg");
		imgDigitalBackground = loadImage("lib/img/sensor_4_back.png");
		imgDigitalGlass = loadImage("lib/img/sensor_4_glass.png");
		imgToerentalBackground = loadImage("lib/img/sensor_5_back.png");
		imgSwitchOn = loadImage("lib/img/sensor_3_on.png");
		imgSwitchOff = loadImage("lib/img/sensor_3_off.png");
		imgSwitchWarning = loadImage("lib/img/sensor_3_warning.png");
		imgLabelGrootZeil = loadImage("lib/img/label_grootzeil.png");
		imgLabelFok = loadImage("lib/img/label_fok.png");
		imgLabelHandmatig = loadImage("lib/img/label_handmatig.png");
		imgLabelMotor = loadImage("lib/img/label_motor.png");
		imgLabelRfids = loadImage("lib/img/label_rfids.png");
		imgLabelVerbinding = loadImage("lib/img/label_verbinding.png");
		imgLabelAccu = loadImage("lib/img/label_accu.png");
		imgLabelToerental = loadImage("lib/img/label_toerental.png");
		imgLabelRoerstand = loadImage("lib/img/label_roerstand.png");

		this.setLayout(null);
		listRfid.setBounds(20, 290, 180, 100);
		listRfid.setLayoutOrientation(JList.HORIZONTAL_WRAP);
		listRfid.setVisibleRowCount(5);
		this.add(listRfid,BorderLayout.CENTER);
		
		
		
		//new InputController().start();
		this.setMinimumSize(new Dimension(600, 300));
		this.setSize(200, 200);
	}

	
	
	/*
	 * 
	 * 
	 * 
	 *      UTILS
	 * 
	 * 
	 * 
	 */
	
	/**
	 * Loads a image into the memory
	 */
	public static BufferedImage loadImage(String path) {
		BufferedImage img = null;
		try {
			img = ImageIO.read(new File(path));
		} catch (IOException ex) {
			Logger.getLogger(MainPanel.class.getName()).log(Level.SEVERE, null,
					ex);
		}
		return img;
	}

	/**
	 * Rotates a wind needle
	 * @param rad The angle
	 * @return The needle
	 */
	private BufferedImage rotateWindImage(double rad){
		BufferedImage img = imgCompassNeedle;
		int w = 180;
		int h = 180;
		BufferedImage dimg = new BufferedImage(w, h, img.getColorModel()
				.getTransparency());
		Graphics2D g = dimg.createGraphics();
		g.translate(75, 0);
		g.rotate(rad, 8, 75);

		g.drawImage(img, null, 0, 0);
		g.dispose();
		return dimg;
	}
	
	/**
	 * Rotates the compass background
	 * @param img The original image
	 * @param rad The angle
	 * @return The rotated image
	 */
	private BufferedImage rotateCompassImage(BufferedImage img, double rad){
		int w = img.getWidth();
		int h = img.getHeight();
		BufferedImage dimg = new BufferedImage(w, h, img.getColorModel()
				.getTransparency());
		Graphics2D g = dimg.createGraphics();
		g.rotate(rad, 85, 85);

		g.drawImage(img, null, 0, 0);
		g.dispose();
		return dimg;
	}

	/**
	 * Rotates a needle image
	 * @param img The needle
	 * @param rad The angle
	 * @return The rotated needle
	 */
	private BufferedImage rotateNeedleImage(BufferedImage img, double rad)
	{
		int w = 180;
		int h = 200;
		BufferedImage copy = new BufferedImage(w, h, img.getColorModel()
				.getTransparency());
		Graphics2D g = copy.createGraphics();
		g.translate(75, 0);
		g.rotate(rad, 9, 85);

		g.drawImage(img, null, 0, 0);
		g.dispose();
		return copy;
	}

	
	
	
	
	
	/*
	 * 
	 * 
	 *     PAINT
	 * 
	 * 
	 */
	
	/**
	 * Paints all sensors
	 * @param g The graphics component
	 */
	@Override
	public void paint(Graphics g)
	{
		super.paint(g);

		g.drawImage(imgBackground, 0, -212, null);

		// Incline sensor

		BufferedImage tmpS = rotateCompassImage(imgIncline, angIncline);
		g.drawImage(tmpS, 20, 100, null);
		g.drawImage(imgGlass, 20, 100, null);

		// Compass sensor
		g.drawImage(rotateCompassImage(imgCompass, angCompass), 220, 100, null);
		g.drawImage(imgCompassBoat,220,100,null);
		g.drawImage(rotateWindImage(angWind), 220, 110, null);
		g.drawImage(imgGlass, 220, 100, null);

		// Grootzeil
		g.drawImage(imgLabelGrootZeil, 420, 20, null);
		g.drawImage(imgSensor, 420, 100, null);
		g.drawImage(rotateNeedleImage(imgNeedle, angGrootzeil-1), 420, 140, null);
		g.drawImage(imgGlass, 420, 100, null);

		// Fok
		g.drawImage(imgLabelFok, 620, 20, null);
		g.drawImage(imgSensor, 620, 100, null);
		g.drawImage(rotateNeedleImage(imgNeedle, angFok+1), 620, 140, null);
		g.drawImage(imgGlass, 620, 100, null);
		
		// Toerental
		g.drawImage(imgLabelToerental, 820, 20, null);
		g.drawImage(imgToerentalBackground, 820, 100, null);
		g.drawImage(rotateNeedleImage(imgNeedle, angToeren-2.4), 820, 100, null); // 0 - 3.6
		g.drawImage(imgGlass, 820, 100, null);

		// Digital sensor
		g.drawImage(imgDigitalBackground, 20, 20, null);
		Font f = null;
		int fontSize = 10;
		try {
			f = Font.createFont(Font.PLAIN, new File("lib/Verdana.ttf"));
			f = f.deriveFont(30f);
			fontSize = f.getSize();
			g.setFont(f);
		} catch (FontFormatException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		g.setColor(Color.black);
		g.drawString(_time, 140, 60);
		g.drawImage(imgDigitalGlass, 20, 20, null);
		
		// Roerstand
		g.drawImage(imgLabelRoerstand, 850, 490, null);
		g.drawImage(imgSensor, 820, 300, null);
		g.drawImage(rotateNeedleImage(imgNeedle, angRoer-1), 820, 340, null);
		g.drawImage(imgGlass, 820, 300, null);
		
		// Switch sensor
		g.drawImage(_isConnected == false?imgSwitchWarning:imgSwitchOn, 290, 320, null);
		g.drawImage(imgLabelVerbinding, 260, 410, null);
		
		g.drawImage(_manualMode == true?imgSwitchOn:imgSwitchOff, 420, 320, null);
		g.drawImage(imgLabelHandmatig, 390, 410, null);

		g.drawImage(_motorMode == true?imgSwitchOn:imgSwitchOff, 550, 320, null);
		g.drawImage(imgLabelMotor, 520, 410, null);
		
		g.drawImage(_accuWarning == true?imgSwitchWarning:imgSwitchOff, 680, 320, null);
		g.drawImage(imgLabelAccu, 650, 410, null);
		
		g.drawImage(imgLabelRfids, 60, 410, null);
		
	}

	
	
	/*
	 * 
	 * 
	 *    INTERUPTS
	 * 
	 * 
	 */
	
	public void AccuMessage(int value)
	{
		_accuWarning = value <= 10?true:false;
		repaint(680,320,50,50);
	}

	public void FokZeilMessage(int value)
	{
		_fzeilValue += value;
		_fzeilCount++;
		if (_fzeilCount > 3) {
			// TODO to radians and calibrate
			angFok = _fzeilValue / _windCount;
			_fzeilCount = 0;
			_fzeilValue = 0.0f;
			this.repaint(620, 100, 170, 175);
		}
	}

	public void GrootZeilMessage(int value)
	{
		_gzeilValue += value;
		_gzeilCount++;
		if (_gzeilCount >= 3) {
			// TODO to radians and calibrate
			angGrootzeil = _gzeilValue / _gzeilCount;
			this.repaint(420, 100, 170, 175);
			_gzeilCount = 0;
			_gzeilValue = 0.0f;
		}
	}

	public void HellingMessage(int value)
	{
		_hellingValue += value;
		_hellingCount++;
		if (_hellingCount >= 3) {
			angIncline = Math
					.toRadians((510 - (_hellingValue / _hellingCount)) * 1.384615385);
			_hellingCount = 0;
			_hellingValue = 0.0f;
			this.repaint(20, 100, 170, 175);
		}
	}

	public void RichtingMessage(int value)
	{
		_richtingValue += value;
		_richtingCount++;
		if (_richtingCount >= 3) {
			angCompass = _richtingValue / _richtingCount;
			_richtingCount = 0;
			_richtingValue = 0.0f;
			this.repaint(220, 100, 170, 175);
		}
	}

	public void ToerenMessage(int value)
	{
		_toerenValue += value;
		_toerenCount++;
		if (_toerenCount >= 3) {
			// TODO do something with toeren value
			// ? _toerenValue / _toerenCount;
			_toerenCount = 0;
			_toerenValue = 0;
		}
	}

	public void WindMessage(int value)
	{
		_windValue += value;
		_windCount++;
		if (_windCount >= 3) {
			angWind = _windValue / _windCount;
			
			_windCount = 0;
			_windValue = 0.0f;
			
			this.repaint(220, 100, 170, 175);
		}
	}

	public void rfidTagMessage(long time, int tag)
	{
		if(_rfidValues.size() > 5) _rfidValues.remove(0);
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(time);
		_rfidValues.add(DateFormatter.formatNumber(c.get(Calendar.HOUR))+":"+DateFormatter.formatNumber(c.get(Calendar.MINUTE))+":"+DateFormatter.formatNumber(c.get(Calendar.SECOND))+" "+tag);
	}
	
	/**
	 * Updates the digital time display on the UI
	 * @param time The current string to be displayed
	 */
	public void setTime(String time)
	{
		_time = time;
		repaint(20,20,220,80);
	}
	

	/**
	 * Updates the manual led on the UI
	 * @param mode True, if turned on
	 */
	public void setManualMode(boolean mode)
	{
		_manualMode = mode;
		repaint(420,320,50,50);
	}
	
	/**
	 * Updates the motor led on the UI
	 * @param mode True, if turned on
	 */
	public void setMotorMode(boolean mode)
	{
		_motorMode = mode;
		repaint(590,320,50,50);
	}
	
	/**
	 * Updates the guther stance on the UI
	 * @param value
	 */
	public void setRoer(int value)
	{
		angRoer = value;
		repaint(820,300,170,175);
	}
	
	/**
	 * Updates the connection led on the UI
	 * @param c True, if connected
	 */
	public void setConnection(boolean c)
	{
		if(c == false)
		{
			MainFrame.getInstance().reconnectButton.setEnabled(true);
			MainFrame.getInstance().reconnectButton.setText("Verbind");
		}
		else
		{
			MainFrame.getInstance().reconnectButton.setEnabled(true);
			MainFrame.getInstance().reconnectButton.setText("Verbreek");
		}
		_isConnected = c;
		repaint(290,320,50,50);
	}
}
